package com.baitengsoft.patentservicemonitor.job.cloud.patent.hub.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * https://www.cnblogs.com/zedosu/p/6665306.html
 *
 * @author wangze
 * @date 2018-08-26 22:09.
 **/
public class CustomThreadPoolExecutor {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomThreadPoolExecutor.class);

    private ThreadPoolExecutor pool = null;


    /**
     * 线程池初始化方法
     * <p>
     * corePoolSize 核心线程池大小----1
     * maximumPoolSize 最大线程池大小----3
     * keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间----30+单位TimeUnit
     * TimeUnit keepAliveTime时间单位----TimeUnit.MINUTES
     * workQueue 阻塞队列----new ArrayBlockingQueue<Runnable>(5)====5容量的阻塞队列
     * threadFactory 新建线程工厂----new CustomThreadFactory()====定制的线程工厂
     * rejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,
     * 即当提交第41个任务时(前面线程都没有执行完,此测试方法中用sleep(100)),
     * 任务会交给RejectedExecutionHandler来处理
     */
    public void init() {
        new ThreadPoolExecutor.AbortPolicy();
        pool = new ThreadPoolExecutor(
                8,
                16,
                15,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(200),
                new CustomThreadFactory(),
                new CustomRejectedExecutionHandler());
    }


    public void destory() {
        try {
            if (pool != null) {
                pool.shutdown();
                while (!pool.awaitTermination(1, TimeUnit.SECONDS)) {
                    System.out.println("正在执行中");
                }
                System.out.println("terminater" + pool.isTerminated());
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

    }


    public ExecutorService getCustomThreadPoolExecutor() {
        return this.pool;
    }

    private static class CustomThreadFactory implements ThreadFactory {
        private AtomicInteger count = new AtomicInteger(0);
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        CustomThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                    poolNumber.getAndIncrement() +
                    "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            String threadName = CustomThreadPoolExecutor.class.getSimpleName() + count.addAndGet(1);
            System.out.println(threadName);
            return t;
        }


    }


    private class CustomRejectedExecutionHandler implements RejectedExecutionHandler {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                // 核心改造点，由blockingqueue的offer改成put阻塞方法
                executor.getQueue().put(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    // 测试构造的线程池
    public static void main(String[] args) throws InterruptedException {
        CustomThreadPoolExecutor exec = new CustomThreadPoolExecutor();
        // 1.初始化
        exec.init();
        ExecutorService pool = exec.getCustomThreadPoolExecutor();
        long start = System.currentTimeMillis();
        for (int i = 1; i <= 10; i++) {
            System.out.println("提交第" + i + "个任务!");
            pool.execute(() -> {

                try {
                    System.out.println(">>>task is running=====");
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        exec.destory();
        long end = System.currentTimeMillis();
        LOGGER.info("运行时长:" + (end - start) / 1000);
    }
}
